#include "universaldataformat.h"
#include <string.h>

char UniversalDataHeader::Version[VerStrLen] = "UDF.V.1.0.0";

UniversalDataHeader::UniversalDataHeader()
{
	CreationTimeExist = 0;
	CoordinatesExist = 0;
	AltitudeExist = 0;
	CurrentExist = 0;
	EMFExist = 0;
	TechDescrExist = 0;
}

bool UniversalDataHeader::Save(ostream &fdescr)
{
	fdescr.write(Version,sizeof(Version));
	fdescr.write((char*)&CreationTimeExist,sizeof(BYTE));
	fdescr.write((char*)&CoordinatesExist,sizeof(BYTE));
	fdescr.write((char*)&AltitudeExist,sizeof(BYTE));
	fdescr.write((char*)&CurrentExist,sizeof(BYTE));
	fdescr.write((char*)&EMFExist,sizeof(BYTE));
	fdescr.write((char*)&TechDescrExist,sizeof(BYTE));
	if(!fdescr.good()) return false;
	return true;
}

bool UniversalDataHeader::Load(istream &fdescr)
{
	char Version1[VerStrLen];
	fdescr.read(Version1,sizeof(Version));
	if(strcmp(Version1,Version) != 0) return false;
	fdescr.read((char*)&CreationTimeExist,sizeof(BYTE));
	fdescr.read((char*)&CoordinatesExist,sizeof(BYTE));
	fdescr.read((char*)&AltitudeExist,sizeof(BYTE));
	fdescr.read((char*)&CurrentExist,sizeof(BYTE));
	fdescr.read((char*)&EMFExist,sizeof(BYTE));
	fdescr.read((char*)&TechDescrExist,sizeof(BYTE));
	if(!fdescr.good()) return false;
	return true;
}

AbstractChannelData::AbstractChannelData()
{
	PointsNumber = 0;
	TimeScaleType = -1; 
	TimeStep = -1;	
	EnforceCoefficient = 0;
	Times = NULL;
	Values = NULL;
}

AbstractChannelData::~AbstractChannelData()
{
	if(Times) delete Times;
	if(Values) delete Values;
	PointsNumber = 0;
	TimeScaleType = -1; 
	TimeStep = -1;	
	EnforceCoefficient = 0;
}

bool AbstractChannelData::Save(ostream &fdescr)
{
	fdescr.write((char*)&PointsNumber,sizeof(int));
	fdescr.write((char*)&TimeScaleType,sizeof(BYTE));
	fdescr.write((char*)&TimeStep,sizeof(double));
	fdescr.write((char*)&EnforceCoefficient,sizeof(double));
	if(!fdescr.good())return false;
	if(TimeScaleType == 1) fdescr.write((char*)Times,PointsNumber * sizeof(double));
	fdescr.write((char*)Values,PointsNumber * sizeof(double));
	if(!fdescr.good())return false;
	return true;
}

bool AbstractChannelData::Load(istream &fdescr)
{
	int _PointsNumber; BYTE _TimeScaleType; double _TimeStep; double _EnforceCoeff;
	fdescr.read((char*)&_PointsNumber,sizeof(int));
	fdescr.read((char*)&_TimeScaleType,sizeof(BYTE));
	fdescr.read((char*)&_TimeStep,sizeof(double));
	fdescr.read((char*)&_EnforceCoeff,sizeof(double));
	if(!fdescr.good())return false;
	Create( _PointsNumber,  _TimeScaleType,  _TimeStep,  _EnforceCoeff);
	if(TimeScaleType == 1) fdescr.read((char*)Times,PointsNumber * sizeof(double));
	else 
		for(int i = 1; i <= PointsNumber; i ++)	
			Times[i-1] = (double)i * TimeStep;
	fdescr.read((char*)Values,PointsNumber * sizeof(double));
	if(!fdescr.good())return false;
	return true;
}

void AbstractChannelData::Create(int _PointsNumber, BYTE _TimeScaleType, double _TimeStep, double _EnforceCoeff)
{
	PointsNumber = _PointsNumber;
	TimeScaleType = _TimeScaleType;
	TimeStep = _TimeStep;
	EnforceCoefficient = _EnforceCoeff;
	if(PointsNumber > 0) 
	{
		Values = new double[PointsNumber];
		Times = new double[PointsNumber];
	}
}

AbstractMultiChannelData::AbstractMultiChannelData()
{
	NumberOfChannels = 0;
	Channels = NULL;
}

AbstractMultiChannelData::~AbstractMultiChannelData()
{
	if(Channels) delete [] Channels;
	NumberOfChannels = 0;
	Channels = NULL;
}

void AbstractMultiChannelData::Create(int _NumOfCh)
{
	if(_NumOfCh <= 0) return;
	NumberOfChannels = _NumOfCh;
	Channels = new AbstractChannelData[NumberOfChannels];
}

bool AbstractMultiChannelData::Save(ostream &fdescr)
{
	fdescr.write((char*)&NumberOfChannels,sizeof(int));
	for(int i = 0; i < NumberOfChannels; i ++)
		if(!Channels[i].Save(fdescr)) return false;
	if(!fdescr.good())return false;
	return true;
}

bool AbstractMultiChannelData::Load(istream &fdescr)
{
	fdescr.read((char*)&NumberOfChannels,sizeof(int));
	Create(NumberOfChannels);
	for(int i = 0; i < NumberOfChannels; i ++)
		if(!Channels[i].Load(fdescr)) return false;
	if(!fdescr.good())return false;
	return true;
}


UniversalDataFrame::UniversalDataFrame(void)
{
	x = 0.;
	y = 0.;
	z = 0.;
}

UniversalDataFrame::~UniversalDataFrame(void)
{
}

bool UniversalDataFrame::Save(ostream &fdescr)
{
	if(!Header.Save(fdescr)) return false;
	if(Header.CreationTimeExist > 0) fdescr.write((char*)&DateAndTime,sizeof(SYSTEMTIME));
	if(Header.CoordinatesExist > 0) 
	{
		fdescr.write((char*)&x,sizeof(double));
		fdescr.write((char*)&y,sizeof(double));
		fdescr.write((char*)&z,sizeof(double));
	}
	if(Header.AltitudeExist > 0) Altitude.Save(fdescr);
	if(Header.CurrentExist > 0) Current.Save(fdescr);
	if(Header.EMFExist > 0) EMF.Save(fdescr);
	if(!fdescr.good())return false;
	return true;
}

bool UniversalDataFrame::Load(istream &fdescr)
{
	if(!Header.Load(fdescr)) return false;
	if(Header.CreationTimeExist > 0) fdescr.read((char*)&DateAndTime,sizeof(SYSTEMTIME));
	if(Header.CoordinatesExist > 0) 
	{
		fdescr.read((char*)&x,sizeof(double));
		fdescr.read((char*)&y,sizeof(double));
		fdescr.read((char*)&z,sizeof(double));
	}
	if(Header.AltitudeExist > 0) Altitude.Load(fdescr);
	if(Header.CurrentExist > 0) Current.Load(fdescr);
	if(Header.EMFExist > 0) EMF.Load(fdescr);
	if(!fdescr.good())return false;
	return true;
}
